// Fill out your copyright notice in the Description page of Project Settings.


#include "ProjectileBullet.h"
#include "GameFramework/Character.h"
#include "Kismet/GameplayStatics.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Blaster/Character/BlasterCharacter.h"
#include "Blaster/PlayerController/BlasterPlayerController.h"
#include "Blaster/BlasterComponents/LagCompensationComponent.h"

AProjectileBullet::AProjectileBullet()
{
	ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(
		TEXT("ProjectileMovementComponent"));
	ProjectileMovementComponent->bRotationFollowsVelocity = true;
	ProjectileMovementComponent->SetIsReplicated(true);
	ProjectileMovementComponent->InitialSpeed = InitialSpeed;
	ProjectileMovementComponent->MaxSpeed = InitialSpeed;
}
#if WITH_EDITOR
void AProjectileBullet::PostEditChangeProperty(FPropertyChangedEvent& Event)
{
	Super::PostEditChangeProperty(Event);
	//Property：更改的实际属性
	//GetFName：获取字段名称
	//NAME_None：特殊零值，表示无名称
	FName PropertyName = Event.Property != nullptr ? Event.Property->GetFName() : NAME_None;
	//GET_MEMBER_NAME_CHECKED：返回FName，同时静态验证成员是否存在这个类中
	if (PropertyName == GET_MEMBER_NAME_CHECKED(AProjectileBullet, InitialSpeed))
	{
		if (ProjectileMovementComponent)
		{
			ProjectileMovementComponent->InitialSpeed = InitialSpeed;
			ProjectileMovementComponent->MaxSpeed = InitialSpeed;
		}
	}
}
#endif

void AProjectileBullet::BeginPlay()
{
	Super::BeginPlay();
	FPredictProjectilePathParams PathParams;
	/**
	//bTraceWithChannel：是否使用跟踪轨道检测碰撞
	PathParams.bTraceWithChannel = true;
	//bTraceWithCollision：是否单条路径寻找碰撞并碰到第一个物体就停下来
	PathParams.bTraceWithCollision = true;
	//DrawDebugTime：在一定时间内的调试线，仅与DrawDebugType::Duration关联
	PathParams.DrawDebugTime = 5.f;
	//DrawDebugType：调试画区间时间选项
	PathParams.DrawDebugType = EDrawDebugTrace::ForDuration;
	//LaunchVelocity：初始化跟踪射线开始的启动速度
	PathParams.LaunchVelocity = GetActorForwardVector() * InitialSpeed;
	//MaxSimTime：针对虚拟导弹的最大模拟时间
	PathParams.MaxSimTime = 4.f;
	//ProjectileRadius：导弹半径，用于当跟踪碰撞的时候
	PathParams.ProjectileRadius = 5.f;
	//SimFrequency：确定模拟中每个子步的大小（分割MaxSimTime时间），建议10~30之间
	PathParams.SimFrequency = 30.f;
	//StartLocation：跟踪射线的开始位置
	PathParams.StartLocation = GetActorLocation();
	//TraceChannel：设置跟踪轨道，若跟踪碰撞被使用
	PathParams.TraceChannel = ECollisionChannel::ECC_Visibility;
	//ActorsToIgnore：当带碰撞跟踪时所忽略的Actors
	PathParams.ActorsToIgnore.Add(this);
	FPredictProjectilePathResult PathResult;
	//PredictProjectilePath：预测受重力影响的虚拟导弹的弧度带着沿弧线的碰撞检测，如碰到事物，则返回true
	UGameplayStatics::PredictProjectilePath(this, PathParams, PathResult);
	*/
}

void AProjectileBullet::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp,
                              FVector NormalImpulse, const FHitResult& Hit)
{
	ABlasterCharacter* OwnerCharacter = Cast<ABlasterCharacter>(GetOwner());
	if (OwnerCharacter)
	{
		ABlasterPlayerController* OwnerController = Cast<ABlasterPlayerController>(OwnerCharacter->Controller);
if (OwnerController)
		{

			const float DamageToCasue = Hit.BoneName.ToString() == FString("head") ? HeadShotDamage : Damage;
			
			if (HasAuthority() && !bUseServerSideRewind)
			{
				//ApplyDamage：通用伤害伤害具体Actor
				UGameplayStatics::ApplyDamage(OtherActor, DamageToCasue, OwnerController, this, UDamageType::StaticClass());
				Super::OnHit(HitComponent, OtherActor, OtherComp, NormalImpulse, Hit);
				return;
			}
			ABlasterCharacter* HitCharacter = Cast<ABlasterCharacter>(OtherActor);
			if (bUseServerSideRewind && OwnerCharacter->GetLagCompensation() && OwnerCharacter->IsLocallyControlled() &&
				OtherActor)
			{
				OwnerCharacter->GetLagCompensation()->ProjectileServerScoreRequest(
					HitCharacter, TraceStart, InitialVelocity,
					OwnerController->GetServerTime() - OwnerController->SingleTripTime);
			}
		}
	}
	Super::OnHit(HitComponent, OtherActor, OtherComp, NormalImpulse, Hit);
}
